package cn.mw.cmdb.viewProcessor;

import cn.mw.cmdb.entity.InputDataAuth;
import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.TableHeaderItemExt;
import cn.mw.cmdb.processor.TableDataProcessorContext;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.entity.cmdb.RelatedDataType;
import cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem;
import cn.mw.microMonitorCommon.entity.userDTO.GroupDTO;
import cn.mw.microMonitorCommon.entity.userDTO.OrgDTO;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.PropertyTypeMoney.isNumeric;
import static cn.mw.cmdb.util.ValConvertUtil.strValueConvert;

public class DataAuthMapViewProcessor implements RelateDataViewProcessor<InstanceInfo, Map> {
    private static final String Prefix = "mapProcessor";
    private String orgKey = Prefix + InputDataAuth.OrgKey;

    private String groupKey = Prefix + InputDataAuth.GroupKey;

    private String userKey = Prefix + InputDataAuth.UserKey;

    private ViewProcessorManage viewProcessorManage;
    private List<TableHeaderItem> tableHeaderItems;

    private Map<String, String> keyNameMap = new HashMap<>();
    private Map<String, String> userDataMap = new HashMap<>();
    private Map<String, String> orgDataMap = new HashMap<>();
    private Map<String, String> groupDataMap = new HashMap<>();

    private Set<String> keyNameSet = new HashSet<>();
    private Map<String, Map<String, String>> authTypeMap = new HashMap<>();


    public DataAuthMapViewProcessor(ViewProcessorManage viewProcessorManage, List<TableHeaderItem> tableHeaderItems) {
        this.viewProcessorManage = viewProcessorManage;
        this.tableHeaderItems = tableHeaderItems;
    }

    @Override
    public void init(InstanceInfo instanceInfo, Map map) {
        //赋值权限数据
        map.put(CMDBTool.getFieldName(InstanceInfo::getUsers), instanceInfo.getUsers());
        map.put(CMDBTool.getFieldName(InstanceInfo::getOrgs), instanceInfo.getOrgs());
        map.put(CMDBTool.getFieldName(InstanceInfo::getOrgIds), instanceInfo.getOrgIds());
        map.put(CMDBTool.getFieldName(InstanceInfo::getGroups), instanceInfo.getGroups());
        map.put(CMDBTool.getFieldName(InstanceInfo::getModelId), instanceInfo.getModelId());
        //设置key对应的表头名称
        for (TableHeaderItem tableHeaderItem : tableHeaderItems) {
            if (tableHeaderItem instanceof TableHeaderItemExt) {
                TableHeaderItemExt tableHeaderItemExt = (TableHeaderItemExt) tableHeaderItem;
                keyNameMap.put(tableHeaderItemExt.getField(), tableHeaderItemExt.getKeyName());
                if (RelatedDataType.dataAuthUser.equals(tableHeaderItem.getParseType())) {
                    userDataMap.put(tableHeaderItemExt.getField(), tableHeaderItemExt.getKeyName());
                    authTypeMap.put(InputDataAuth.UserKey, userDataMap);
                } else if (RelatedDataType.dataAuthOrg.equals(tableHeaderItem.getParseType())) {
                    orgDataMap.put(tableHeaderItemExt.getField(), tableHeaderItemExt.getKeyName());
                    authTypeMap.put(InputDataAuth.OrgKey, orgDataMap);
                } else if (RelatedDataType.dataAuthGroup.equals(tableHeaderItem.getParseType())) {
                    groupDataMap.put(tableHeaderItemExt.getField(), tableHeaderItemExt.getKeyName());
                    authTypeMap.put(InputDataAuth.GroupKey, groupDataMap);
                }
            }
        }


        map.forEach((k, v) -> {
            if (keyNameMap != null && keyNameMap.containsKey(strValueConvert(k))) {
                String foreignKeyId = keyNameMap.get(k);
                Object authData = map.get(foreignKeyId);
                Object convaerVal = null;
                if (authData != null) {
                    if (authData instanceof List) {
                        List<String> ids = new ArrayList<>();
                        for (Object obj : (List) authData) {
                            if (obj != null && obj instanceof List) {
                                //如果是机构部门类型，数据为二位数组，只需要获取每个list中的最后一个值，即为本身机构的id
                                List objList = (List) obj;
                                if (CollectionUtils.isNotEmpty(objList)) {
                                    viewProcessorManage.addFieldIdSet(strValueConvert(k), strValueConvert(objList.get(objList.size() - 1)));
                                    ids.add(strValueConvert(objList.get(objList.size() - 1)));
                                }
                            } else {
                                if (!"".equals(strValueConvert(obj))) {
                                    viewProcessorManage.addFieldIdSet(strValueConvert(k), strValueConvert(obj));
                                    ids.add(strValueConvert(obj));
                                }
                            }
                        }
                        convaerVal = StringUtils.collectionToCommaDelimitedString(ids);
                    } else {
                        if (!"".equals(strValueConvert(authData)) && !strValueConvert(authData).contains(",") && isNumeric(authData)) {
                            viewProcessorManage.addFieldIdSet(strValueConvert(k), strValueConvert(authData));
                            convaerVal = strValueConvert(authData);
                        }
                    }
                }
                if (null != convaerVal) {
                    //重新赋值
                    map.put(k, convaerVal);
                }
            }
        });

    }


    @Override
    public void selectRelateData(TableDataProcessorContext context) throws Exception {
        //查询用户关联数据
        MwUserApi mwUserApi = (MwUserApi) context.get(ViewConvertContext.MwuserApiKey);

        authTypeMap.forEach((k, v) -> {
            String authType = k;
            Map<String, String> dataMap = v;
            Set<String> authDataInfo = new HashSet<>();
            for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                String key = entry.getKey();
                if (viewProcessorManage.getFieldIdSet(key) != null) {
                    authDataInfo.addAll(viewProcessorManage.getFieldIdSet(key));
                }
            }
            if (InputDataAuth.OrgKey.equals(authType)) {
                if (null != authDataInfo) {
//                    List<Long> orgIds = new ArrayList<>();
//                    for(String str : authDataInfo){
//                        if(str.startsWith("[")&& str.endsWith("]")){
//                            str = str.substring(1,str.length()-1);
//                            orgIds.add(longValueConvert(str));
//                        }else{
//                            orgIds.add(longValueConvert(str));
//                        }
//                    }


                    List<Long> orgIds = authDataInfo.stream().mapToLong(data -> Long.valueOf(data)).boxed().collect(Collectors.toList());
                    List<OrgDTO> orgDTOS = mwUserApi.getAllOrg();
                    Set<Long> longSet = orgDTOS.stream().map(s -> s.getId()).collect(Collectors.toSet());
                    for (Long orgId : orgIds) {
                        Map<Long, String> parentInfoMap = getParentInfoMap(longSet, orgDTOS, orgId);
                        viewProcessorManage.addFieldIdMap(authType, orgId.toString(), parentInfoMap.get(orgId));
                    }
                }
            }
            if (InputDataAuth.GroupKey.equals(authType)) {
                if (null != authDataInfo) {
                    List<Long> groupIds = authDataInfo.stream().mapToLong(data -> Long.valueOf(data)).boxed().collect(Collectors.toList());
                    List<GroupDTO> groupDTOS = mwUserApi.getGroupListByIds(groupIds);
                    if (null != groupDTOS) {
                        for (GroupDTO groupDTO : groupDTOS) {
                            viewProcessorManage.addFieldIdMap(authType, groupDTO.getId().toString(), groupDTO.getGroupName());
                        }
                    }
                }
            }
            if (InputDataAuth.UserKey.equals(authType)) {
                if (null != authDataInfo) {
                    List<Long> userIds = authDataInfo.stream().mapToLong(data -> Long.valueOf(data)).boxed().collect(Collectors.toList());
                    List<MwUser> mwUsers = mwUserApi.getUsersByUserIds(userIds);
                    if (null != mwUsers) {
                        for (MwUser mwUser : mwUsers) {
                            viewProcessorManage.addFieldIdMap(authType, mwUser.getId().toString(), mwUser.getNickName());
                        }
                    }
                }
            }
        });
    }


    public static Map<Long, String> getParentInfoMap(Set<Long> orgIds, List<OrgDTO> orgDtos, Long id) {
        List<Long> parentIds = new ArrayList<>();
        List<String> parentNames = new ArrayList<>();
        findParentInfo(orgIds, orgDtos, id, parentIds, parentNames);

        // 反转列表顺序
        Collections.reverse(parentIds);
        Collections.reverse(parentNames);

        // 构造结果 Map
        Map<Long, String> resultMap = new HashMap<>();
        resultMap.put(id, String.join("/", parentNames));

        return resultMap;
    }

    private static void findParentInfo(Set<Long> orgIds, List<OrgDTO> orgDtos, Long id, List<Long> parentIds, List<String> parentNames) {
        Optional<OrgDTO> currentOrg = orgDtos.stream().filter(org -> org.getId().equals(id)).findFirst();
        if (currentOrg.isPresent() && currentOrg.get().getPid() != null) {
            if (orgIds.contains(currentOrg.get().getId())) {
                parentIds.add(currentOrg.get().getId());
                parentNames.add(currentOrg.get().getOrgName());
                findParentInfo(orgIds, orgDtos, currentOrg.get().getPid(), parentIds, parentNames);
            }
        }
    }

    @Override
    public void setRelateData(Map map) {
        //从返回数据中获取id,并设置对应的名称
        authTypeMap.forEach((k, v) -> {
            Map<String, String> authDataMap = v;
            for (Map.Entry<String, String> entry : authDataMap.entrySet()) {
                String key = entry.getKey();
                doSet(map, key, k);
            }
        });
    }

    /**
     * @param idMap            数据源
     * @param idMapKey         替换的字段id
     * @param inputDataAuthKey 转换方法类型
     */
    private void doSet(Map idMap, String idMapKey, String inputDataAuthKey) {
        Object idObj = idMap.get(idMapKey);
        if (null != idObj) {
            String idStr = (String) idObj;
            Map<String, String> dataMap = viewProcessorManage.getFieldIdMap(inputDataAuthKey);
            if (StringUtils.hasText(idStr) && null != dataMap) {
                String[] ids = StringUtils.commaDelimitedListToStringArray(idStr);
                List<String> names = new ArrayList<>();
                if (null != ids) {
                    for (String id : ids) {
                        String name = dataMap.get(id);
                        if (StringUtils.hasText(name)) {
                            names.add(name);
                        }
                    }
                }
                if (names.size() > 0) {
                    idMap.put(idMapKey, StringUtils.collectionToCommaDelimitedString(names));
                }
            }
        }
    }
}
